from typing import Any, List
from fastapi import APIRouter, Body, Depends, HTTPException
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session

from app import crud, models, schemas
from app.api import deps
from app.core import security
from app.core.config import settings
from app.core.redis import redis_client
from app.core.rabbitmq import rabbitmq_client

# 创建路由器实例
router = APIRouter()

@router.post("/", response_model=schemas.User)
def create_user(*, db: Session = Depends(deps.get_db), user_in: schemas.UserCreate) -> Any:
    """创建新用户
    
    注册新用户并保存到数据库，同时通过RabbitMQ异步发送欢迎邮件
    
    Args:
        db: 数据库会话，通过依赖注入获取
        user_in: 用户创建模型，包含用户注册信息
        
    Returns:
        新创建的用户对象
        
    Raises:
        HTTPException: 当邮箱或用户名已被注册时抛出
    """
    user = crud.user.get_by_email(db, email=user_in.email)
    if user:
        raise HTTPException(
            status_code=400,
            detail="该邮箱已被注册",
        )
    user = crud.user.get_by_username(db, username=user_in.username)
    if user:
        raise HTTPException(
            status_code=400,
            detail="该用户名已被使用",
        )
    user = crud.user.create(db, obj_in=user_in)
    # 异步发送欢迎邮件
    rabbitmq_client.publish(
        exchange="user",
        routing_key="welcome_email",
        body=user.email
    )
    return user

@router.post("/login", response_model=schemas.Token)
def login(db: Session = Depends(deps.get_db), form_data: OAuth2PasswordRequestForm = Depends()) -> Any:
    """用户登录
    
    验证用户凭据并生成访问令牌
    
    Args:
        db: 数据库会话，通过依赖注入获取
        form_data: OAuth2密码表单，包含用户名和密码
        
    Returns:
        包含访问令牌和令牌类型的Token对象
        
    Raises:
        HTTPException: 当用户名/密码错误或用户被禁用时抛出
    """
    user = crud.user.authenticate(db, username=form_data.username, password=form_data.password)
    if not user:
        raise HTTPException(status_code=400, detail="用户名或密码错误")
    elif not crud.user.is_active(user):
        raise HTTPException(status_code=400, detail="用户已被禁用")
    access_token = security.create_access_token(user.id)
    # 将token存入Redis缓存
    redis_client.set(f"user_token:{user.id}", access_token, expire=settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60)
    return {"access_token": access_token, "token_type": "bearer"}

@router.get("/me", response_model=schemas.User)
def read_user_me(current_user: models.User = Depends(deps.get_current_user)) -> Any:
    """获取当前用户信息
    
    返回当前已认证用户的信息
    
    Args:
        current_user: 当前用户对象，通过依赖注入获取
        
    Returns:
        当前用户对象
    """
    return current_user

@router.put("/me", response_model=schemas.User)
def update_user_me(*, db: Session = Depends(deps.get_db), password: str = Body(None), full_name: str = Body(None), email: str = Body(None), current_user: models.User = Depends(deps.get_current_user)) -> Any:
    """更新当前用户信息
    
    允许用户更新自己的个人信息
    
    Args:
        db: 数据库会话，通过依赖注入获取
        password: 新密码，可选
        full_name: 新全名，可选
        email: 新邮箱，可选
        current_user: 当前用户对象，通过依赖注入获取
        
    Returns:
        更新后的用户对象
    """
    user_in = schemas.UserUpdate(password=password, full_name=full_name, email=email)
    user = crud.user.update(db, db_obj=current_user, obj_in=user_in)
    return user

@router.get("/", response_model=List[schemas.User])
def read_users(db: Session = Depends(deps.get_db), skip: int = 0, limit: int = 100, current_user: models.User = Depends(deps.get_current_superuser)) -> Any:
    """获取用户列表（仅超级管理员）
    
    返回系统中的用户列表，支持分页
    
    Args:
        db: 数据库会话，通过依赖注入获取
        skip: 跳过的记录数，用于分页
        limit: 返回的最大记录数，用于分页
        current_user: 当前用户对象，必须是超级管理员
        
    Returns:
        用户对象列表
    """
    users = crud.user.get_multi(db, skip=skip, limit=limit)
    return users

@router.get("/{user_id}", response_model=schemas.User)
def read_user_by_id(user_id: int, current_user: models.User = Depends(deps.get_current_user), db: Session = Depends(deps.get_db)) -> Any:
    """根据ID获取用户信息
    
    返回指定ID的用户信息，普通用户只能查看自己的信息
    
    Args:
        user_id: 要查询的用户ID
        current_user: 当前用户对象，通过依赖注入获取
        db: 数据库会话，通过依赖注入获取
        
    Returns:
        指定ID的用户对象
        
    Raises:
        HTTPException: 当普通用户尝试查看其他用户信息时抛出
    """
    user = crud.user.get(db, id=user_id)
    if user == current_user:
        return user
    if not crud.user.is_superuser(current_user):
        raise HTTPException(
            status_code=400, detail="该操作需要超级管理员权限"
        )
    return user

@router.delete("/{user_id}", response_model=schemas.User)
def delete_user(*, db: Session = Depends(deps.get_db), user_id: int, current_user: models.User = Depends(deps.get_current_superuser)) -> Any:
    """删除用户（仅超级管理员）
    
    删除指定ID的用户
    
    Args:
        db: 数据库会话，通过依赖注入获取
        user_id: 要删除的用户ID
        current_user: 当前用户对象，必须是超级管理员
        
    Returns:
        被删除的用户对象
        
    Raises:
        HTTPException: 当用户不存在时抛出
    """
    user = crud.user.get(db, id=user_id)
    if not user:
        raise HTTPException(
            status_code=404,
            detail="用户不存在"
        )
    user = crud.user.delete(db, id=user_id)
    return user